/**
 * 增强型虚拟选择器类
 * 用于处理大数据量的select下拉选择器，通过虚拟滚动优化性能
 */
class LayuiFormVirtualSelect {
  /**
   * 构造函数
   * @param {Object} options - 配置选项
   * @param {Object} options.selectName - 选择器名称映射
   * @param {Object} options.form - Layui form 实例
   * @param {Object} options.$ - Layui jQuery 实例
   * @param {number} options.itemHeight - 每个选项的高度，默认42
   * @param {number} options.visibleItems - 可见选项数量，默认10
   * @param {number} options.bufferItems - 缓冲选项数量，默认5
   * @param {number} options.maxHeight - 下拉列表最大高度，默认300
   */
  constructor(options = {}) {
    // 初始化基础配置和数据存储
    // this.selectName = options.selectName || {};
    this.dataMap =
      options.dataMap instanceof Map
        ? options.dataMap
        : new Map(Object.entries(options.dataMap || {}));
    this.searchTextMap = new Map();
    this.form = options.form;
    this.$ = options.$;

    // 修复配置项获取方式
    const configOptions = options.config || {};
    this.config = {
      itemHeight: configOptions.itemHeight || 42,
      visibleItems: configOptions.visibleItems || 10,
      bufferItems: configOptions.bufferItems || 5,
      maxHeight: configOptions.maxHeight || 300,
    };

    this.initData();
  }
  initData() {
    // 使用Map的forEach方法遍历数据
    this.dataMap.forEach((data, selectId) => {
        setTimeout(() => {
            this.loadVirtualOptions(selectId, data);
        }, 500);
    });
  }

  /**
   * 加载数据到指定的选择器
   * @param {string} selectId - 选择器ID
   * @param {Array} data - 选项数据数组
   */
  loadData(selectId, data) {
    this.dataMap.set(selectId, data);
    this.loadVirtualOptions(selectId, data);
  }

  /**
   * 批量加载数据到多个选择器
   * @param {Object} dataMap - 选择器ID和数据的映射对象
   */
  loadBatchData(dataMap) {
    for (const [selectId, data] of Object.entries(dataMap)) {
      this.loadData(selectId, data);
    }
  }

  /**
   * 加载虚拟选项
   * @param {string} selectId - 选择器ID
   * @param {Array} data - 选项数据数组
   */
  loadVirtualOptions(selectId, data) {
    // 初始化基本参数
    const select = document.getElementById(selectId);
    const { itemHeight, visibleItems, bufferItems, maxHeight } = this.config;
    let startIndex = 0;
    // const select_name = this.selectName[select.id] ?? select.name;
    let currentScrollTop = 0;
    /**
     * 初始化选择器的选项
     * 创建并添加所有选项到select元素
     */
    const initializeSelectOptions = () => {
      requestAnimationFrame(() => {
        // console.log(`初始化选择器的选项`);
        const fragment = document.createDocumentFragment();
        const defaultOption = select.querySelector('option[value=""]');
        // 如果select元素中已存在option标签则返回
        if (select.getElementsByTagName("option").length >= 1) {
          // 处理空数据情况
          if (data.length === 0 && select.hasAttribute("lay-creatable")) {
            const text = this.searchTextMap.get(selectId);
            if (text) {
              const option = document.createElement("option");
              option.value = text;
              option.text = text;
              fragment.appendChild(option);
            }
          }
          select.appendChild(fragment);
          return;
        }

        select.innerHTML = "";
        // 添加默认选项
        select.appendChild(
        //   defaultOption ?? new Option(`请选择${select_name}`, "")
          defaultOption ?? new Option(`请选择`, "")

        );

        // 添加数据选项
        data.forEach((item) => {
          const option = document.createElement("option");
          option.value = item.value;
          option.text = item.text;
          fragment.appendChild(option);
        });
        select.appendChild(fragment);
      });
    };
    let chooseValue = {};

    /**
     * 更新可见选项
     * @param {number} scrollTop - 滚动位置
     */
    const updateVisibleOptions = (scrollTop) => {
      currentScrollTop = scrollTop;
      requestAnimationFrame(() => {
        const $select = this.$(select).next(".layui-form-select");
        const $dl = $select.find("dl.layui-anim");

        // 确保数据是数组
        const dataArray = Array.isArray(data) ? data : [];

        // 计算可见区域的起始和结束索引
        startIndex = Math.floor(scrollTop / itemHeight);
        const start = Math.max(0, startIndex);
        const end = Math.min(
          dataArray.length,
          startIndex + visibleItems + bufferItems
        );

        // 清空并重新渲染可见区域
        $dl.empty();

        // 添加上部空白占位
        if (start > 0) {
          $dl.append(
            this.$("<div>").css({
              height: start * itemHeight + "px",
              padding: 0,
              margin: 0,
            })
          );
        }

        // 添加默认选项
        $dl.append(
          this.$('<dd lay-value="">请选择</dd>').addClass("layui-select-tips")
        );

        // 处理空数据情况
        if (dataArray.length === 0 && select.hasAttribute("lay-creatable")) {
          const searchText = this.searchTextMap.get(selectId);
          if (searchText) {
            $dl.empty();
            $dl.append(
              this.$(`<dd lay-value="${searchText}">${searchText}</dd>`)
            );
          }
        }

        // 添加可见选项
        for (let i = start; i < end; i++) {
          const item = dataArray[i];
          const $dd = this.$("<dd></dd>")
            .attr("lay-value", item.value)
            .text(item.text);
        //    console.log(item,chooseValue.value);
          if (item.value == chooseValue.value) {//高亮当前选中项
            $dd.addClass("layui-this");
          }
          $dl.append($dd);
        }

        // 添加下部空白占位
        if (end < data.length) {
          $dl.append(
            this.$("<div>").css({
              height: (data.length - end) * itemHeight + "px",
              padding: 0,
              margin: 0,
            })
          );
        }

        // 设置总高度
        const totalHeight = (data.length + 1) * itemHeight;
        $dl.height(totalHeight);
      });
    };

    /**
     * 过滤数据
     * @param {string} searchText - 搜索文本
     * @returns {Array} 过滤后的数据
     */
    const getFilterData = (searchText) => {
      if (!searchText) return this.dataMap.get(selectId) || [];
      const searchValue = searchText.toLowerCase();
      return (this.dataMap.get(selectId) || []).filter(
        (item) =>
          item.text.toLowerCase().includes(searchValue) ||
          String(item.value).toLowerCase().includes(searchValue)
      );
    };

    /**
     * 事件处理初始化
     * 设置选择、点击、搜索和滚动事件
     */
    const eventhandle = () => {
      const $select = this.$(select).next(".layui-form-select");
      const $dl = $select.find("dl.layui-anim");
      // 选择事件处理
      this.form.on("select", (data) => {
        const curselectId = data.elem.id;
        if (curselectId !== selectId) return;

        //   $input.trigger("focus");
        // if (data.value) {
        // 从dl中获取选中项的文本
        const selectedText = $dl.find(`dd[lay-value="${data.value}"]`).text();
        // console.log('选择器变更:', {
        //     selectId: curselectId,
        //     value: data.value,
        //     text: selectedText
        // });
       
        const $input = $select.find("input");
        chooseValue = {
          value: data.value,
          text: selectedText,
        };
        // 获取当前选中的选项文本
        // 设置input的placeholder为当前选中值,如果没有选中值则显示"请选择"
        $input.attr("placeholder", data.value?selectedText : "请选择");
        this.searchTextMap.set(selectId, '');
        select.innerHTML = '';
        select.appendChild(
          new Option(selectedText, data.value, true, true)
        );
 
      });
      let ticking = false;
      // 点击事件处理（带防抖）
      const handleClick = () => {
        updateVisibleOptions(0);
      };

      // 搜索事件处理（带防抖）
      const handleSearch = (e) => {
        requestAnimationFrame(() => {
          const searchValue = this.$(e.target).val().toLowerCase();
          this.searchTextMap.set(selectId, searchValue);
          
          // 只更新当前选择器的数据
          const filteredData = getFilterData(searchValue);
          data = filteredData;
          const $currentSelect = this.$(select);
          const $currentFormSelect = $currentSelect.next(".layui-form-select");
          const $currentInput = $currentFormSelect.find("input");

          // 更新当前选择器的虚拟列表
          updateVisibleOptions(0);
          
          // 更新搜索框状态
          $currentInput.val(searchValue);
          $currentInput.trigger("focus");
        });
      };

      const handleScroll = () => {
        if (!ticking) {
          requestAnimationFrame(() => {
            updateVisibleOptions($dl.scrollTop());
            ticking = false;
          });
          ticking = true;
        }
      };
      $dl.off("scroll").on("scroll", handleScroll);
      // 绑定事件
      $select.off("click").on("click", ".layui-select-title", handleClick);
      $select.off("keyup").on("keyup", "input", handleSearch);
    };

    // 初始化流程
    this.form.render("select");
    requestAnimationFrame(() => {
      // 确保 DOM 已经渲染完成
      setTimeout(() => {
        const $select = this.$(select).next(".layui-form-select");
        if ($select.length) {
          updateVisibleOptions(0);
          eventhandle();
        } else {
          console.warn(`选择器 ${selectId} 未正确初始化`);
        }
      }, 50);
    });

  }

  /**
   * 防抖函数
   * @param {Function} fn - 需要防抖的函数
   * @param {number} delay - 延迟时间（毫秒）
   * @returns {Function} 防抖处理后的函数
   */
  debounce(fn, delay = 500) {
    let timer = null;
    return (...args) => {
      if (timer) clearTimeout(timer);
      timer = setTimeout(() => fn.apply(this, args), delay);
    };
  }

  requestAnimationFrameFunc(func) {
    // 处理逻辑
    requestAnimationFrame(func);
  }
}